//--- Projeto Domus
// interactionsource.com
// Koji Pereira, Andre Veloso e Marcos Paulo

/*
 Projeto Domus
 interactionsource.com
 Koji Pereira, Andre Veloso e Marcos Paulo

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/


package com.interactionsource.control;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Vector;

import com.interactionsource.event.ContinuousEvent;
import com.interactionsource.event.TriggerEvent;
import com.interactionsource.input.wiimoteosc.WiimoteOSCDevice;
import com.interactionsource.output.midi.EventoMIDIOut;
import com.interactionsource.output.midi.GerenciadorMIDI;


/**
 * @author andrevj
 * 
 * Manages Input and Output connections
 * Saves and load from file
 * 
 * To extend Input and Output devices, this class must be modified 
 *
 */
public class Manager {

	protected Vector<WiimoteOSCDevice> wiimoteOSCDevices;

	protected GerenciadorMIDI gerenciadorMIDI;

	protected String pathArquivosConfig = null;

	public Manager() {

		this.gerenciadorMIDI = new GerenciadorMIDI();
		this.wiimoteOSCDevices = new Vector<WiimoteOSCDevice>();
	}


	public int readConfigFile(String filename) {
		try {

			String saidaDebug = new String();

			// initialize file and create values
			BufferedReader in = new BufferedReader(new FileReader(filename));		

			String line;
			String token;

			int position = 0;

			line = in.readLine();
			if(!line.startsWith("INIT")) {
				//Erro na sintaxe do arquivo
				return -1;
			}

			while(in.ready()) {


				if(line.startsWith("INIT")) {
					//Encontrado um dispositivo 

					if(line.indexOf("WIIMOTEOSC") != -1) {
						//encontrado um dispositivo OSC

						line = in.readLine();

						int port = Integer.parseInt(line);

						wiimoteOSCDevices.add(new WiimoteOSCDevice(port));

						line = in.readLine();

						while (!line.startsWith("END")) {						

							StringTokenizer st = new StringTokenizer(line,";");

							while (st.hasMoreTokens()) {
								String tipoEvento = st.nextToken();

								token = st.nextToken();

								token = st.nextToken();

								if (token.equals("MIDI")) {

									String nomeMIDI = st.nextToken();
									String tipoMIDI = st.nextToken();
									int canalMIDI = Integer.parseInt(st.nextToken());
									int dadoMIDI = Integer.parseInt(st.nextToken());

									int tipoMIDIInt = 0;

									for (int i=0; i<EventoMIDIOut.TIPOS_MIDI.length; i++) {
										if (EventoMIDIOut.TIPOS_MIDI[i].equals(tipoMIDI))
											tipoMIDIInt = i;

									}

									wiimoteOSCDevices.lastElement().addEventListenerByType(tipoEvento, pathArquivosConfig, 
											this.gerenciadorMIDI.getNewEventoMIDIOut(
													nomeMIDI, tipoMIDIInt, canalMIDI, dadoMIDI
											)
									);

								}



							}


							line = in.readLine();

						}


					}



				}
				line = in.readLine();
			}

			System.out.println("Manager - Arquivo " + filename + " Lido com sucesso ");

			in.close();

			return 0;

		} catch (Exception e) {
			System.out.println("Error: Read from File!");
			e.printStackTrace();
			return -1;
		}
	}

	public int saveConfigFile(String filename) {

		try {

			String configLine;

			// initialize file and get values
			BufferedWriter out = new BufferedWriter(new FileWriter(filename+".csv"));

			//Salva os WiimoteOSC

			for (int i=0; i < wiimoteOSCDevices.size(); i++) {

				out.write("INIT WIIMOTEOSC " + (i+1) );
				out.newLine();

				out.write( Integer.toString(wiimoteOSCDevices.elementAt(i).getOscPort()) );
				out.newLine();

				//Salva os gestos identificados
				if (wiimoteOSCDevices.elementAt(i).getGestureTriggerEventListener().size() > 0) {

					for (int j=0; j<wiimoteOSCDevices.elementAt(i).getGestureTriggerEventListener().size(); j++) {
						//configLine = WiimoteOSCDevice.GESTURE + ";"
						configLine = "GESTURE_" + i + ";"
						+ TriggerEvent.TRIGGER_EVENT + ";"
						+ wiimoteOSCDevices.elementAt(i).getGestureTriggerEventListener().elementAt(j).toString();

						out.write(configLine);
						out.newLine();						

					}


				}				

				if (wiimoteOSCDevices.elementAt(i).getAccellXContinuousEventListener() != null) {
					configLine = WiimoteOSCDevice.ACCELL_X + ";"
					+ ContinuousEvent.CONTINUOUS_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getAccellXContinuousEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getAccellYContinuousEventListener() != null) {
					configLine = WiimoteOSCDevice.ACCELL_Y + ";"
					+ ContinuousEvent.CONTINUOUS_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getAccellYContinuousEventListener().toString();

					out.write(configLine);
					out.newLine();
				}	

				if (wiimoteOSCDevices.elementAt(i).getAccellZContinuousEventListener() != null) {
					configLine = WiimoteOSCDevice.ACCELL_Z + ";"
					+ ContinuousEvent.CONTINUOUS_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getAccellZContinuousEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButton1TriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_1 + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButton1TriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButton2TriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_2 + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButton2TriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}	

				if (wiimoteOSCDevices.elementAt(i).getButtonATriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_A + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonATriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonBTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_B + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonBTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonHomeTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_HOME + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonHomeTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonMinusTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_MINUS + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonMinusTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonPlusTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_PLUS + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonPlusTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonUpTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_UP + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonUpTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonDownTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_DOWN + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonDownTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonLeftTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_LEFT + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonLeftTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getButtonRightTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.BUTTON_RIGHT + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getButtonRightTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getMotionStartTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.MOTION_START + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getMotionStartTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				if (wiimoteOSCDevices.elementAt(i).getMotionStopTriggerEventListener() != null) {
					configLine = WiimoteOSCDevice.MOTION_STOP + ";"
					+ TriggerEvent.TRIGGER_EVENT + ";"
					+ wiimoteOSCDevices.elementAt(i).getMotionStopTriggerEventListener().toString();

					out.write(configLine);
					out.newLine();
				}

				out.write("END WIIMOTEOSC " + (i+1)  );
				out.newLine();

			}
			// close file
			out.flush();
			out.close();
			return 0;
		} catch (IOException e) {
			System.out.println("Error: Write to File!");
			e.printStackTrace();
			return -1;
		}		

	}

	/**
	 * @return the gerenciadorMIDI
	 */
	public GerenciadorMIDI getGerenciadorMIDI() {
		return gerenciadorMIDI;
	}

	/**
	 * @param gerenciadorMIDI the gerenciadorMIDI to set
	 */
	public void setGerenciadorMIDI(GerenciadorMIDI gerenciadorMIDI) {
		this.gerenciadorMIDI = gerenciadorMIDI;
	}

	public void addWiimoteOSCDevice(WiimoteOSCDevice wiimoteOSCDevice) {
		wiimoteOSCDevices.add(wiimoteOSCDevice);

	}

	public void addWiimoteOSCDevice(int oscPort) {
		wiimoteOSCDevices.add(new WiimoteOSCDevice(oscPort));

	}

	public WiimoteOSCDevice getWiimoteOSCDeviceAt(int position) {
		return wiimoteOSCDevices.elementAt(position);

	}


	public int getWiimoteOSCDevicesCount() {
		return wiimoteOSCDevices.size();

	}

	/**
	 * @return the pathArquivosConfig
	 */
	public String getPathArquivosConfig() {
		return pathArquivosConfig;
	}


	/**
	 * @param pathArquivosConfig the pathArquivosConfig to set
	 */
	public void setPathArquivosConfig(String pathArquivosConfig) {
		this.pathArquivosConfig = pathArquivosConfig;
	}

	public void iniciaTreinoGestosWiimote(int idWiimote) {
		wiimoteOSCDevices.elementAt(idWiimote).iniciaTreinoGesto();
	}

	public void terminaTreinoGestoWiimote(int idWiimote) {
		wiimoteOSCDevices.elementAt(idWiimote).terminaTreinoGesto();
	}

	public void salvaReconhecimentoGestoWiimote(int idWiimote) {
		wiimoteOSCDevices.elementAt(idWiimote).salvaGesto();
	}
	
	public void iniciaReconhecimentoGestoWiimote(int idWiimote) {
		wiimoteOSCDevices.elementAt(idWiimote).iniciaReconhecimentoGesto();
	}

	public void resetConfig() {
		this.gerenciadorMIDI = null;
		this.wiimoteOSCDevices = null;

		this.gerenciadorMIDI = new GerenciadorMIDI();
		this.wiimoteOSCDevices = new Vector<WiimoteOSCDevice>();

		System.out.println("Manager - Resetando configuracao atual - resetConfig");


	}

}
